LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-22-2011, 07:41 AM   #1
raevin
Member
 
Registered: Jul 2004
Distribution: Arch Linux, Ubuntu
Posts: 80

Rep: Reputation: 16
[C] socket connection reset by peer


Been trying to figure this one out for about a day now. Basically, my program gets so far to sending and receiving data, but at the same point, send() comes back as "-1" and says that the connection was reset by the peer. I'm not sure why this is, as the code was working fine before I put in some code for reading the buffer size first. It seems to be that the server is sending data faster than the client receives it, would using sleep(1) after each sendall() be a better idea to stop the race condition?

Edit I should also mention that this isn't using select() for asynch sockets, just using a fork() call instead. /Edit

Edit 2 Sorry for the bumping (if edits cause this). But, following a trace of tcpdump, the RST flag is being set and I'm not sure why, as the socket isn't being closed anywhere near the code.[/b]

Here's the code in question:

Network code:
Code:
/**
 * sendall()
 * s:           Socket [file descriptor] to send data to        [in]
 * buffer:      The data to send to the socket                  [in]
 *
 * Recursive send() for socket, since TCP/IP can't guarantee all of buffer will be sent in one go.
 *
 * Returns 0 on failure, otherwise total bytes sent.
 **/
int sendall(int s, char *buffer){
        int pos = 0;
        int len = strlen(buffer);
        int left = len;
        int curr = 0;

                while(pos < len){
D(("socket = %d, pos = %d, left = %d", s, pos, left));
                        curr = send(s, buffer+pos, left, 0);

                        if(curr == -1){
                                D(("error = %d", errno));
                                perror("send()");
                                return 0;
                         }

D(("curr = %d", curr));

                        pos += curr;
                        left -= curr;
                }

        memset(&buffer, '\0', strlen(buffer));

        return pos;
}

int recvbufflen(int s){
        char *tmp = (char*)malloc(sizeof(char) * 5);
        memset(tmp, '\0', sizeof(tmp));

        recv(s, tmp, 5, 0);

        int len = atoi(tmp);

        free(tmp);

        return len;
}

void sendbufflen(int s, int len){
        char *tmp = (char*)malloc(sizeof(char) * 5);
        memset(tmp, '\0', sizeof(tmp));
D(("strlen = %d", len));
        sprintf(tmp, "%05d", len);

        if(!sendall(s, tmp))
                D(("error sendbufflen() -> sendall()"));

        free(tmp);
}
Server code:
Code:
                       // Get the client's B value
                        bufflen = recvbufflen(connfd);
                        recv(connfd, buff, bufflen, 0);
                        str2mpz(buff, B);

                        // Tell the client our A value
                        sendbufflen(connfd, strlen(szA));
                        sendall(connfd, szA);

                        // We generate our secret key with the same formulas as A
                        mpz_powm_sec(Ssk, B, Ss, P);

                        // Tell the client the key size of the Viegnere Cipher (26, 54, or 96)
                        sprintf(buff, "%d", vhkey);
                        sendbufflen(connfd, strlen(buff));
                        sendall(connfd, buff);
Clinet code (causing the reset for some reason):
Code:
        // B = (G ^ Cs)(mod P)
        mpz_powm_sec(B, G, Cs, P);
        mpz2str(B, szB);
 
        // Tell the server what our B value is
        sendbufflen(sockfd, strlen(szB));
D(("sockfd = %d", sockfd));
        sendall(sockfd, szB);

        // Get the server's A value
        bufflen = recvbufflen(sockfd);
D(("bufflen = %d", bufflen));
        recv(sockfd, buff, bufflen, 0);
        str2mpz(buff, A);
D(("HI!"));
D((...)) is a macro for debugging code (uses printf()).

Last edited by raevin; 07-22-2011 at 08:19 AM. Reason: Reset flag is being set
 
Old 07-22-2011, 08:37 AM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
In your sendall() function, I believe the following is a bug:
Code:
memset(&buffer, '\0', strlen(buffer));
The 'buffer' is already a pointer to a location in memory, thus you do not need to pass it's address to memset(). What you want memset() to do is clear the string being pointed to by 'buffer'; instead you are clearing the memory location, and then possibly some additional memory (depending on the length of the string), with the code above.

I would also recommend that you perform error checking when calling recv(). You may not necessarily receive all of the data you expect with merely one call.
 
Old 07-22-2011, 09:07 AM   #3
raevin
Member
 
Registered: Jul 2004
Distribution: Arch Linux, Ubuntu
Posts: 80

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by dwhitney67 View Post
In your sendall() function, I believe the following is a bug:
Code:
memset(&buffer, '\0', strlen(buffer));
The 'buffer' is already a pointer to a location in memory, thus you do not need to pass it's address to memset(). What you want memset() to do is clear the string being pointed to by 'buffer'; instead you are clearing the memory location, and then possibly some additional memory (depending on the length of the string), with the code above.

I would also recommend that you perform error checking when calling recv(). You may not necessarily receive all of the data you expect with merely one call.
Didn't think it was a bug, but I fixed it anyways, thanks! As for doing error checking on recv(), it works when I don't do use the below code to capture all the buffer data, but when I do the below code, it hangs at recv() for some reason:
Code:
int recvall(int s, char *buffer, int len){
D(("Receiving %d bytes from %d", len, s));
        int curr = 0;
        int pos = 0;   
        int left = len;

        /**
         * If we weren't using blocking I/O for sockets, could do "!= 0" instead...
         * However, "-1" is the only check possible right now...
         **/
        while(pos < len){ 
D(("while(%d < %d)", pos, len));
                curr = recv(s, buffer+pos, left, 0);

                if(curr == -1){
                        perror("recvall()");
                        pos = 0;
                        break;
                }

                pos += curr; 
                left -= curr;
D(("Read %d bytes (%d / %d total)", curr, pos, len));
        }

        return pos;
}
This is a blocking system, but I just find it weird that it works when its not inside of a while() loop, but doesn't as soon as I put it inside of one.
 
Old 07-22-2011, 09:21 AM   #4
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
When calling recv(), the return value of -1 is not necessarily indicative of a "fatal" error. Check the value of errno; if it is EINTR or EAGAIN (or EWOULDBLOCK), then I would suggest that you return to the top of the loop.

P.S. Personally, I always use select() to determine when it is appropriate to call recv().

Last edited by dwhitney67; 07-22-2011 at 09:22 AM.
 
Old 07-22-2011, 09:25 AM   #5
raevin
Member
 
Registered: Jul 2004
Distribution: Arch Linux, Ubuntu
Posts: 80

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by dwhitney67 View Post
When calling recv(), the return value of -1 is not necessarily indicative of a "fatal" error. Check the value of errno; if it is EINTR or EAGAIN (or EWOULDBLOCK), then I would suggest that you return to the top of the loop.

P.S. Personally, I always use select() to determine when it is appropriate to call recv().
I'll do that then, and see what happens. Just whenever I read about recv() it says that -1 is error, but never thought to check errno. Also, doesn't select() only work for asynch sockets?
 
Old 07-22-2011, 09:33 AM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by raevin View Post
Also, doesn't select() only work for asynch sockets?
It works for both blocking and non-blocking sockets.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
fatal: Read from socket failed: Connection reset by peer prakash.akumalla Linux - Newbie 0 07-18-2008 04:42 AM
ERROR reading from socket: Connection reset by peer sweetytweety Linux - Newbie 3 05-16-2008 05:21 AM
Connection reset by peer: why? stupendus Linux - Software 5 08-07-2007 12:50 AM
SSH fatal: Read from socket failed: Connection reset by peer humbletech99 Linux - Networking 3 01-03-2007 06:41 PM
Connection reset by peer mijohnst Linux - Networking 7 07-14-2004 11:14 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:01 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration